package view.subscriberpanels;

import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.HashSet;
import java.util.Set;

import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JSlider;
import javax.swing.JTree;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreePath;

import prefuse.data.expression.Predicate;
import prefuse.data.expression.parser.ExpressionParser;
import prefuse.data.query.ObjectRangeModel;
import prefuse.util.ui.JRangeSlider;
import view.ViewManager;
import view.util.ViewUtil;
import view.visualizations.MeetZoomVis;
import view.visualizations.RaceTableVis;
import view.visualizations.XCVis;
import data.DataManager;

/**
 * Panel for filtering the vis. Clicking on things here should change what's visible
 * in the vis and (theoretically) in the selection panel. The second part doesn't work.
 */
public class FilteringPane extends VisSubscriber {
	
	private JTree locationFilterTree;
	private JRangeSlider yearSlider;
	private JList courseList;
	private String query;
	
	private void setupView() {
		query = "";
		this.setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
		this.setAlignmentY(Component.TOP_ALIGNMENT);
		
		JLabel titleLabel = (JLabel) ViewUtil.createLabelWithAlignment("Filtering", CENTER_ALIGNMENT);
		titleLabel.setFont(new Font(this.getFont().getName(), Font.BOLD, this.getFont().getSize()+2));
		this.add(titleLabel);
		this.add(Box.createRigidArea(new Dimension(0,20)));
	}
	
	@Override
	public void showOverallView() {
		this.removeAll();
		setupView();
		this.add(ViewUtil.createLabelWithAlignment("Team Filtering", JLabel.LEFT_ALIGNMENT));
		createTeamTree();
//		locationFilterTree.setMinimumSize(new Dimension(200, 400));
		JScrollPane locationScrollPane = new JScrollPane(locationFilterTree);
		locationScrollPane.setPreferredSize(new Dimension(180, 300));
		locationScrollPane.setMaximumSize(new Dimension(180, 300));
		this.add(locationScrollPane);
//		this.add(locationFilterTree);
		this.add(new JSeparator(JSeparator.HORIZONTAL));
		
		
		this.add(ViewUtil.createLabelWithAlignment("Meet Adjustment", JLabel.LEFT_ALIGNMENT));
		Set<Object> meets = DataManager.getInstance().getUniqueColumnEntries("Meet");
		final JComboBox meetSelectBox = new JComboBox(meets.toArray());
		this.add(meetSelectBox);
		final JSlider meetOffsetSlider = new JSlider(-120, 120);
		this.add(meetOffsetSlider);
		final JLabel offsetLabel = new JLabel("Offset: 0s");
		this.add(offsetLabel);
		JButton clearOffset = new JButton("Reset");
		this.add(clearOffset);
		
		meetOffsetSlider.addChangeListener(new ChangeListener() {
			@Override
			public void stateChanged(final ChangeEvent e) {
				JSlider source = (JSlider)e.getSource();
			    if (!source.getValueIsAdjusting()) {
			    	offsetLabel.setText("Offset: " + source.getValue() + "s");
			        DataManager.setOffset((String) meetSelectBox.getSelectedItem(), source.getValue());
			        ViewManager.updateVis();
			    }
			}
		});
		
		meetSelectBox.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				int offset = DataManager.getOffset((String) meetSelectBox.getSelectedItem());
				meetOffsetSlider.setValue(offset);
				offsetLabel.setText("Offset: " + offset + "s");
			}
		});
		
		clearOffset.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				DataManager.getInstance().clearOffsets();
				ViewManager.updateVis();
				meetOffsetSlider.setValue(0);
				offsetLabel.setText("Offset: 0s");
			}
		});
		
		
		
//		this.add(ViewUtil.createLabelWithAlignment("Additional Filters", JLabel.CENTER_ALIGNMENT));
//		this.add(Box.createVerticalStrut(20));
		
		// year filter
//		this.add(ViewUtil.createLabelWithAlignment("Year", JLabel.LEFT_ALIGNMENT));
//		Box yearFilter = new Box(BoxLayout.LINE_AXIS);
//		yearFilter.setMaximumSize(new Dimension(200, 20));
//		yearFilter.add(Box.createHorizontalStrut(25));
//		yearSlider = new JRangeSlider(2005, 2010, 2005, 2010, JRangeSlider.HORIZONTAL);
//		yearFilter.add(yearSlider);
//		this.add(yearFilter);
//		this.add(Box.createVerticalStrut(10));
//		
//		// course filter
//		this.add(ViewUtil.createLabelWithAlignment("Course", JLabel.LEFT_ALIGNMENT));
//		String[] courses = {"Course 1", "Course 2"};
//		courseList = new JList(courses);
//		this.add(courseList);
		
		
		
		
		this.add(Box.createVerticalGlue());
		this.add(Box.createVerticalGlue());
		this.add(Box.createVerticalGlue());
		this.add(Box.createVerticalGlue());
		this.add(Box.createVerticalGlue());
		this.add(Box.createVerticalGlue());
		this.add(Box.createVerticalGlue());
		this.add(Box.createVerticalGlue());
		this.add(Box.createVerticalGlue());
		this.add(Box.createVerticalGlue());
		this.add(Box.createVerticalGlue());
		this.add(Box.createVerticalGlue());
		this.add(Box.createVerticalGlue());
		this.add(Box.createVerticalGlue());
		this.add(Box.createVerticalGlue());
		this.add(Box.createVerticalGlue());
		this.add(Box.createVerticalGlue());
		this.add(Box.createVerticalGlue());
		this.add(Box.createVerticalGlue());
	}
	
	@Override
	void showDateZoomView() {
		reapplyQuery();
	}
	@Override
	void showMeetZoomView() {
		reapplyQuery();
	}
	@Override
	void showTableView() {
		reapplyQuery();
	}
	
	private void reapplyQuery() {
		ViewManager.getInstance().addFilterQuery("school", query);
	}
	
	private void createTeamTree() {
		
		DefaultMutableTreeNode top = new DefaultMutableTreeNode("Schools");
		DefaultMutableTreeNode dulles = new DefaultMutableTreeNode("Dulles District");
		top.add(dulles);
		HashSet<Object> teams = DataManager.getInstance().getUniqueColumnEntries("School");
		HashSet<Object> dullesTeams = DataManager.getInstance().getDullesTeams();
		for (Object team : dullesTeams) {
			dulles.add(new DefaultMutableTreeNode(team.toString()));
		}
		for (Object team : teams) {
			if (!dullesTeams.contains(team)) {
				top.add(new DefaultMutableTreeNode(team.toString()));
			}
		}
		locationFilterTree = new JTree(top);
		locationFilterTree.addMouseListener(new MouseListener() {
			
			@Override
			public void mouseReleased(MouseEvent e) {
			}
			
			@Override
			public void mousePressed(MouseEvent e) {
			}
			
			@Override
			public void mouseExited(MouseEvent e) {
			}
			
			@Override
			public void mouseEntered(MouseEvent e) {
			}
			
			@Override
			public void mouseClicked(MouseEvent e) {
				// double click
				if (e.getClickCount() == 2 && !e.isConsumed()) {
					ViewManager.selectAllVisibleRunners();
				    e.consume();
				}
				
			}
		});
		locationFilterTree.addTreeSelectionListener(new TreeSelectionListener() {
			
			@Override
			public void valueChanged(TreeSelectionEvent e) {
				TreePath[] paths = locationFilterTree.getSelectionPaths();
				query = "";
				String selected = ((DefaultMutableTreeNode)paths[0].getLastPathComponent()).toString();
				if (!selected.equals("Schools")) {
					for (int i = 0; i < paths.length; i++){
						selected = ((DefaultMutableTreeNode)paths[i].getLastPathComponent()).toString();
						if (i == 0) {
							query = "School = '" + escapeString(selected) + "'";
						} else {
							query += " OR School = '" + escapeString(selected) + "'";
						}
					}
				}
				ViewManager.getInstance().addFilterQuery("school", query);
				ViewManager.notifyTableChange();
				XCVis vis = ViewManager.getCurrentVis();
				if (vis instanceof RaceTableVis) { // baad coding
					if (query.equals("")) {
						((RaceTableVis) vis).filterTable(null);
					} else {
						((RaceTableVis) vis).filterTable((Predicate)(ExpressionParser.parse(query)));
					}
					ViewManager.notifySubscribers();
				}
			}
		});
	}
	
	private String escapeString(final String s) {
		String[] splitString = s.split("'");
		String retString = "";
		for (int i=0; i<splitString.length; i++) {
			retString += splitString[i];
			if (!(i==splitString.length-1)) {
				retString += "\\'";
			}
		}
		return (retString.equals("")) ? s : retString;
	}
	@Override
	void updateView() {
		
	}
}
